package com.tank.factory;

import com.almasb.fxgl.core.math.FXGLMath;
import com.almasb.fxgl.dsl.FXGL;
import com.almasb.fxgl.dsl.components.EffectComponent;
import com.almasb.fxgl.dsl.components.ExpireCleanComponent;
import com.almasb.fxgl.dsl.components.HealthIntComponent;
import com.almasb.fxgl.dsl.components.ProjectileComponent;
import com.almasb.fxgl.entity.Entity;
import com.almasb.fxgl.entity.EntityFactory;
import com.almasb.fxgl.entity.SpawnData;
import com.almasb.fxgl.entity.Spawns;
import com.almasb.fxgl.entity.components.CollidableComponent;
import com.almasb.fxgl.texture.AnimatedTexture;
import com.almasb.fxgl.texture.AnimationChannel;
import com.almasb.fxgl.ui.ProgressBar;
import com.tank.components.EnemyComponent;
import com.tank.components.PlayerComponent;
import com.tank.components.TankComponent;
import com.tank.components.BulletLevelComponent;
import com.tank.constant.Config;
import com.tank.constant.Direction;
import com.tank.constant.GameType;
import javafx.scene.paint.Color;

public class TankEntityFactory implements EntityFactory {

    @Spawns("player")
    public Entity newPlayer(SpawnData data) {
        HealthIntComponent hpComponent = new HealthIntComponent(Config.PLAYER_MAX_HEALTH);
        hpComponent.setValue(Config.PLAYER_MAX_HEALTH);
        ProgressBar hpBar = new ProgressBar();
        hpBar.setWidth(39);
        hpBar.setTranslateY(42);
        hpBar.setLabelVisible(false);
        hpBar.setFill(Color.LIGHTGREEN);
        hpBar.maxValueProperty().bind(hpComponent.maxValueProperty());
        hpBar.currentValueProperty().bind(hpComponent.valueProperty());
        hpBar.currentValueProperty().addListener((o, ov, nv) -> {
            if (nv.intValue() <= Config.PLAYER_MAX_HEALTH * 0.4) {
                hpBar.setFill(Color.RED);
            } else if (nv.intValue() <= Config.PLAYER_MAX_HEALTH * 0.8) {
                hpBar.setFill(Color.YELLOW);
            } else {
                hpBar.setFill(Color.LIGHTGREEN);
            }
        });
        return FXGL.entityBuilder(data)
                .type(GameType.PLAYER)
                .viewWithBBox("tank/H1U.png")
                .view(hpBar)
                .with(new EffectComponent())
                .with(new BulletLevelComponent())
                .with(hpComponent)
                .with(new TankComponent())
                .with(new PlayerComponent())
                .with(new CollidableComponent(true))
                .build();
    }

    @Spawns("enemy")
    public Entity newEnemy(SpawnData data) {
        int enemyType = FXGLMath.random(1, Config.ENEMY_TYPE_COUNT);
        return FXGL.entityBuilder(data)
                .type(GameType.ENEMY)
//                .bbox(BoundingShape.box(Config.TANK_WIDTH, Config.TANK_HEIGHT))
                .viewWithBBox("tank/E" + enemyType + "U.png")
                .with(new EffectComponent())
                .with(new BulletLevelComponent())
                .with(new HealthIntComponent(3))
                .with(new TankComponent())
                .with(new EnemyComponent(enemyType))
                .with(new CollidableComponent(true))
                .build();
    }

    @Spawns("bullet")
    public Entity newBullet(SpawnData data) {
        Direction direction = data.get("direction");
        GameType ownerType = data.get(Config.OWNER_TYPE);
        if (ownerType == GameType.PLAYER) {
            FXGL.play("normalFire.wav");
        }
        CollidableComponent collidableComponent = new CollidableComponent(true);
        collidableComponent.addIgnoredType(ownerType);
        return FXGL.entityBuilder(data)
                .type(GameType.BULLET)
                .viewWithBBox("bullet/normal.png")
                .with(new ProjectileComponent(direction.getVector(), Config.BULLET_SPEED))
                .with(collidableComponent)
                .build();
    }

    @Spawns("explosion")
    public Entity newExplosion(SpawnData data) {
        FXGL.play("normalBomb.wav");
        AnimationChannel ac = new AnimationChannel(FXGL.image("explode/explosion.png"), Config.EXPLODE_TIME, Config.EXPLOSION_FRAME_COUNT);
        AnimatedTexture at = new AnimatedTexture(ac);
        return FXGL.entityBuilder(data)
                .view(at.play())
                .with(new ExpireCleanComponent(Config.EXPLODE_TIME))
                .build();
    }

    @Spawns("silentExplosion")
    public Entity newSilentExplosion(SpawnData data) {
        AnimationChannel ac = new AnimationChannel(FXGL.image("explode/explosion.png"), Config.EXPLODE_TIME, Config.EXPLOSION_FRAME_COUNT);
        AnimatedTexture at = new AnimatedTexture(ac);
        return FXGL.entityBuilder(data)
                .view(at.play())
                .with(new ExpireCleanComponent(Config.EXPLODE_TIME))
                .build();
    }

    @Spawns("doomExplosion")
    public Entity newDoomExplosion(SpawnData data) {
        FXGL.play("rocketBomb.wav");
        AnimationChannel ac = new AnimationChannel(FXGL.image("explode/explosion.png"), Config.EXPLODE_TIME, Config.EXPLOSION_FRAME_COUNT);
        AnimatedTexture at = new AnimatedTexture(ac);
        return FXGL.entityBuilder(data)
                .view(at.play())
                .with(new ExpireCleanComponent(Config.EXPLODE_TIME))
                .build();
    }


    @Spawns("mildExplosion")
    public Entity newMildExplosion(SpawnData data) {
        FXGL.play("e_fire.wav");
        AnimationChannel ac = new AnimationChannel(FXGL.image("explode/explosion.png"), Config.EXPLODE_TIME, Config.EXPLOSION_FRAME_COUNT);
        AnimatedTexture at = new AnimatedTexture(ac);
        return FXGL.entityBuilder(data)
                .view(at.play())
                .with(new ExpireCleanComponent(Config.EXPLODE_TIME))
                .build();
    }
}
